﻿using System;
using System.Data;

namespace Viyi.Util.Data.Converter
{
    /// <summary>
    /// <c>DataTable</c>列数据转换器基类，完成了对数据列的处理。
    /// 其子类只需要实现对数据的转换即可。
    /// </summary>
    public abstract class DataTableColumnConverter : IDataTableColumnConverter
    {
        const string TempColumnPrefix = "_TEMP_COL_";

        /// <summary>
        /// 判断是否删除源列
        /// </summary>
        protected bool IsDeleteOriginalColumn { get; set; }

        /// <summary>
        /// 数据表
        /// </summary>
        protected DataTable DataTable { get; private set; }

        /// <summary>
        /// 将指定列的数据转换为其它格式表示
        /// 如果newColumnName为null，则使用新的值替换旧的值（新列换旧列）
        /// 否则为新值创建新的列
        /// </summary>
        /// <param name="data">数据表</param>
        /// <param name="columnName">原列名称</param>
        /// <param name="newColumnName">新列名称</param>
        /// <remarks>如果新列名为<c>null</c>、<c>string.Empty</c>或仅包含空白字符，
        /// 则转换后的新列会被用来代替源列，源列数据会被丢弃。</remarks>
        public void Convert(DataTable data, string columnName, string newColumnName = null)
        {
            if (data == null) { return; }
            else { DataTable = data; }

            if (data.Rows.Count == 0 && newColumnName == null)
            {
                // new column should be always create even no data,
                // when newColumnName is specified.
                return;
            }

            if (string.IsNullOrWhiteSpace(columnName))
            {
                throw new ArgumentException("columnName不能为空或空字符串");
            }

            int columnIndex = data.Columns.IndexOf(columnName);
            if (columnIndex < 0) { throw new IndexOutOfRangeException("不存在列：" + columnName); }

            DataColumn newColumn = GenerateColumn(data.Columns[columnIndex], newColumnName);
            int newColumnIndex = data.Columns.IndexOf(newColumn);

            foreach (DataRow row in data.Rows) { Convert(row, columnIndex, newColumnIndex); }

            if (IsDeleteOriginalColumn)
            {
                data.Columns.RemoveAt(columnIndex);
                newColumn.ColumnName = columnName;
            }
        }

        /// <summary>
        /// 根据源数据列和新列名，产生新列
        /// </summary>
        /// <param name="originColumn">源列</param>
        /// <param name="newColumnName">新列名称</param>
        /// <returns></returns>
        protected virtual DataColumn GenerateColumn(DataColumn originColumn, string newColumnName)
        {
            bool isDeleteOldColumn = false;
            if (string.IsNullOrWhiteSpace(newColumnName))
            {
                isDeleteOldColumn = true;
                newColumnName = TempColumnPrefix + originColumn.ColumnName;
            }

            IsDeleteOriginalColumn = isDeleteOldColumn;
            return DataTable.Columns.Add(newColumnName);
        }

        /// <summary>
        /// 逐行转换数据
        /// </summary>
        /// <param name="row">数据行</param>
        /// <param name="columnIndex">源列索引</param>
        /// <param name="newColumnIndex">新列索引</param>
        protected abstract void Convert(DataRow row, int columnIndex, int newColumnIndex);
    }
}
